home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
The Programmer Disk
/
The Programmer Disk (Microforum).iso
/
xpro
/
extra
/
pro13
/
tsr.doc
< prev
next >
Wrap
Text File
|
1993-09-04
|
61KB
|
809 lines
------------------------------------------------------------------------
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| T S R |
| |
| Version 1.5 |
| |
| Copyright (C) 1993, Geoff Friesen B.Sc. |
| All rights reserved. |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
------------------------------------------------------------------------
------------------------------------------------------------------------
| |
| History |
| ------- |
| |
| TSR TOOLKIT has a long history. I first became interested in build- |
| ing TSRs back in the fall of 1988. I tried building a few but found |
| the amount of work involved very tiring. If I had a nickle for each |
| time I had to reboot the computer while testing, I could retire. It |
| became apparent that some mechanism was needed to handle TSR details |
| allowing me to concentrate on the application. This would save alot |
| of time. In 1989, I put together my first toolkit. I pre-wrote the |
| resident and installation kernels. The library was in object form |
| and could quickly be linked with the application module. Although |
| this technique worked and saved alot of time, it was pretty bloated. |
| There were other problems as well. After giving up on the toolkit |
| for a few years, I decided to take one last crack in 1992. I began |
| development work on TSR TOOLKIT. TSR TOOLKIT has gone through alot |
| of versions. Version 1.5 is the latest and the most complete. For |
| the first time, this toolkit feels like a winner. I am very glad to |
| be able to share this package with you and hope that you will find |
| it useful in writing your own TSRs. |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
------------------------------------------------------------------------
- 2 -
------------------------------------------------------------------------
| |
| TSR Structure |
| ------------- |
| |
| Before you can write your own TSRs, it would be a good idea to get |
| comfortable with the internal structure. In this section, I want to |
| explain how the kernels work and how everything fits together. You |
| can examine the source code when you create a TSR (or look at TSR.C) |
| for additional information. Let's start with a diagram. |
| |
| ---------------- |
| | RESIDENT | |
| | KERNEL | |
| ---------------- |
| | APPLICATION | |
| ---------------- |
| | INSTALLATION | |
| | KERNEL | |
| ---------------- |
| |
| This is as basic as it gets. A TSR is structured as a .COM format |
| program. Internally, a TSR resembles a sandwich. The resident and |
| installation kernels surround the application. When you create a |
| TSR, you can focus your attention on creating this application. The |
| kernels have already been written for you. The option does exist to |
| extend the installation kernel to add customization to your program. |
| We'll see this later on in this document. |
| |
| The resident kernel has one basic goal. It must respond to hotkey |
| presses, delay activation until the computer system is in a stable |
| state, and then perform a launch sequence. The launch sequence is |
| sort of equivalent to the start up code in a regular application. |
| The stack is switched, registers are saved and then initialized as |
| appropriate, interrupt vectors are saved, the keyboard buffer is |
| emptied, and other tasks are performed prior to calling the main () |
| function (the entry point) within the application. Once main () has |
| returned to the launch sequence, everything is restored and the TSR |
| exits as if the hotkey had never been pressed. |
| |
| The basic goal behind the installation kernel is to install the TSR |
| once and only once and provide a means to remove the TSR (uninstall) |
| when necessary. |
| |
| Over the years, these kernels have grown in size and capability. |
| They perform a staggering amount of work. In order to really under- |
| stand how TSRs work, we're going to have to look in detail at these |
| kernels. Here we go. |
| |
| |
| |
------------------------------------------------------------------------
- 3 -
------------------------------------------------------------------------
| |
| When a TSR is loaded into memory, execution begins at address 100h |
| because the TSR is a .COM program. The JMP instruction at 100h will |
| cause execution to continue at the first address in the installation |
| kernel. |
| |
| The personal identification section (aka communications API) follows |
| the JMP instruction. The communications API is a collection of use- |
| ful pieces of information organized in a standard manner and access- |
| ible to other TSRs and regular programs. The first piece of infor- |
| mation is the hotkey character. This is the ASCII letter or digit |
| of the default hotkey. The equivalent scancode follows. Following |
| a NULL byte is the version number. The version number was designed |
| to make it easy to change the kernel structure for subsequent ver- |
| sions of TSR TOOLKIT without crashing previously written TSRs and |
| regular programs which access the kernel. All versions prior to 1.4 |
| have version number zero. Version zero should not be considered as |
| a reliable means of identifying different kernel locations since I |
| made a number of changes without changing this number. Version 1.4 |
| has version number 1. Version 1.5 has version number 2. These num- |
| bers are stored in binary in a single byte. The address of the main |
| procedure follows. I have not encountered a use for this knowledge |
| as yet but will undoubtedly find a use in the future. The starting |
| address of the installation kernel follows. Again, this information |
| is present but not being used at this time. A two-byte field marked |
| "reserved" follows. I may use this field in the future to extend |
| the communications API past the signature field which follows. The |
| signature identifies the TSR and always starts with "TSR:". The sig |
| is stored as an ASCIZ string (a C-style string with a terminating 0 |
| byte). |
| |
| The resident data section follows the communications API. All data |
| storage required by the resident kernel is located in this section. |
| The beep flag variable (beepf) is really part of the communications |
| API (even though this is not indicated). This variable will always |
| following the terminating 0 byte of the signature. |
| |
| The resident code section follows the data section. This section is |
| divided into a variety of redirected interrupt vectors, the launch |
| sequence procedure, the sound API, the XMS API, and the stack. |
| |
| Interrupt 9 is activated whenever a hotkey is pressed. If the TSR |
| is not already active (as indicated by the tsr_state variable then |
| interrupt 9 sets this variable to a TRIGGERED status. Interrupt 9 |
| will also generate a beep if the beep flag (beepf) is set. The pur- |
| pose of this beep is to provide positive assurance to the user that |
| the hotkey has been acknowledged. Sometimes a TSR may not activate |
| immediately when its hotkey is pressed for the following reasons. |
| |
| |
------------------------------------------------------------------------
- 4 -
------------------------------------------------------------------------
| |
| DOS may not be in a stable state. The extended memory manager found |
| in HIMEM.SYS may not be in a stable state. The BIOS disk service |
| (interrupt 13h) may be active. The chaining order of installed TSRs |
| may be such that a TSR cannot activate until a currently active TSR |
| becomes inactive. |
| |
| Interrupts 8 and 28h monitor tsr_state. Interrupt 8, the timer tick |
| interrupt, activates about 18.2 times per second (unless the timer |
| frequency has been changed). Interrupt 28h is called repeatedly by |
| the DOS buffered keyboard input function (function 10) when DOS is |
| waiting for input at the command line (a function code such as 10 is |
| placed in the AH register and interrupt 21h is called to request DOS |
| perform a function such as buffered keyboard input). When DOS is |
| waiting for a command at the command line, DOS is active but is in a |
| state where it is safe to call DOS functions higher than 12. |
| |
| When interrupts 8 and 28h detect that tsr_state has been set to the |
| TRIGGERED status, they perform four tests to ensure that everything |
| is as stable as possible. The first test is to make sure that the |
| critical error handler is not active. The second is to ensure that |
| DOS is not operating in a critical section. The third is to be cer- |
| tain that interrupt 13h is not active. The fourth and final test is |
| to make certain that HIMEM.SYS is not active. If all four tests are |
| passed then the launch sequence procedure is called to complete the |
| activation. |
| |
| Interrupt 13h is redirected to monitor itself by setting a flag upon |
| input and resetting this flag upon output. Interrupts 8 and 28h use |
| this flag in testing to see if it is safe to activate. |
| |
| Interrupts 1bh and 23h have also been redirected but only by the |
| launch sequence procedure. This was done to ensure an even higher |
| degree of reliability in the event that CTRL-BREAK should be pressed |
| when a standard I/O function is called (not a console I/O function |
| whose code is less than 13). |
| |
| The reason why TSR TOOLKIT does not support any version of DOS less |
| than 3.30 has to do with the critical error handler interrupt. This |
| interrupt has been set to return a FAIL code whenever called. Doing |
| this ensures that you never need to include a critical error handler |
| in your application. DOS 3.30 was the first version of DOS to offer |
| a FAIL code which always causes the offending interrupt 21h function |
| to return to the application with a suitable error code in the AX |
| register. |
| |
| |
| |
| |
| |
------------------------------------------------------------------------
- 5 -
------------------------------------------------------------------------
| |
| The multiplex interrupt needs to be redirected as well. When 4310h |
| is passed in the AX register, interrupt 2fh responds with the entry |
| address to the HIMEM.SYS XMS handler (if HIMEM.SYS is installed). |
| One of the tests performed by interrupts 8 and 28h is to ensure that |
| HIMEM.SYS is not active when a TSR activates. It turns out that the |
| XMS handler is not reentrant. By redirecting interrupt 2fh, we can |
| pass a different entry point address. This new handler (see the XMS |
| XMS_rdriver procedure) can set a flag upon entry, call the handler, |
| and reset the flag upon exit allowing interrupts 8 and 28h to carry |
| out their test. |
| |
| The launch sequence procedure is called by either interrupt 8 and |
| 28h to complete the activation process. This procedure must setup |
| an appropriate environment so that the application can execute in a |
| completely safe environment. The first step is to switch stacks. A |
| stack follows this procedure. There is no telling what stack will |
| be in use when the launch sequence procedure begins execution. This |
| stack could have room for several hundred to several thousand bytes. |
| On the other hand, there may only be enough room for a handful. Our |
| application needs its own stack. Who knows how many local variables |
| will be defined. The launch sequence procedure switches back to the |
| original stack just before it exits. All registers are saved on the |
| switched stack since any could be modified. Interrupts are enabled |
| and the string move direction flag in the processor flags register |
| is cleared to ensure that any string instructions accessed by the |
| application will operate in a forward manner. The data segment (DS) |
| register is set to the same segment as the code segment (since the |
| application is written in C, it will be accessing static data via |
| its DGROUP which has its address set to the data segment address). |
| Interrupts 1bh, 23h, and 24h are redirected for greater reliability. |
| Interrupt 24h is the critical error handler interrupt. The program |
| segment prefix (PSP) of the currently active application (or TSR) |
| which we are interrupting is saved and then set to our PSP. The |
| same thing happens to the data transfer area (DTA). Extended error |
| information is also saved. Whenever a DOS function is called and an |
| error occurs, information is saved constituting the extended error |
| state. This tells us more about what error occurred and where it |
| occurred. We now come to the strangest section of the launch seq- |
| uence procedure. In this section, we redirect interrupts 8, 9, 16h, |
| and 1ch. We actually set them to values that they had before the |
| TSR was installed. I would rather not have done this but it turns |
| out that various Microsoft programs including DOS 5.0 EDIT/QBASIC |
| and Microsoft Word 5.0 crash when a TSR is activated with these ints |
| redirected. Go figure Microsoft. The unfortunate part about this |
| is you cannot take advantage of the kernel's interrupt 8 to add some |
| additional timing code for creating timers. You must install your |
| own. Finally, we flush the keystroke buffer, disconnect the speaker |
| and hide the mouse cursor. We then call the application main () |
| function and restore everything to its original state prior to exit. |
------------------------------------------------------------------------
- 6 -
------------------------------------------------------------------------
| |
| The SOUND API follows. This API provides four functions that your |
| application can use to take advantage of sound and processor speed- |
| independent timing. These functions are documented in a separate |
| section. |
| |
| The XMS API follows the SOUND API and contains a group of functions |
| that your application can call to access extended memory. These |
| functions are documented in a separate section. |
| |
| The resident code section and the resident kernel conclude with the |
| stack. The stack follows the XMS API and builds down towards it. I |
| chose a default stack size of 256 bytes but you have the option of |
| increasing the stack as will be seen later. |
| |
| The application code follows the stack. The code comprising EXTRA. |
| ASM (if specified) would be loaded following the application. |
| |
| The installation kernel begins with the installation data section. |
| This section contains all of the data local to this section. The |
| command tail address is used by the command tail parsing logic to |
| locate the next parse location on the command tail. The psp is used |
| to refer to the segment of a resident TSR. The scancodes table is |
| used to convert a hotkey letter read from the command tail to an |
| equivalent scancode which will be stored in the communications API. |
| A variety of messages along with a variable to hold the major por- |
| tion of the DOS version number complete this section. |
| |
| The first piece of code has the task of displaying the TSR title. |
| This gives you the ability to personalize your TSR. The TSR title |
| is actually stored in your application .C file. The examples found |
| in TSREX.ZIP show how the title would be formatted. Every line must |
| end with a carriage return/line feed sequence. |
| |
| The next step is to obtain the DOS version number and make sure that |
| the version is at least 3.30 (because of the critical error handler |
| FAIL code). We save the major portion in the ver variable so we can |
| access this later (HIMEM.SYS was only introduced with DOS 5.0 and so |
| we cannot redirect the multiplex interrupt if our DOS version is not |
| 5.0 or higher). |
| |
| We obtain the addresses of the critical error and critical section |
| flags since these must be tested by interrupts 8 and 28h as part of |
| the task in ensuring that DOS is stable. |
| |
| The next step is to search for a previously installed copy (it would |
| be wasteful of memory to install more than one copy). The search is |
| also important when we wish to uninstall (if the TSR has not been |
| installed then how can we uninstall). |
| |
------------------------------------------------------------------------
- 7 -
------------------------------------------------------------------------
| |
| Command tail parsing follows. The command tail is stored in the PSP |
| at offset 81h. The last byte in the command tail must be a carriage |
| return character. We skip leading whitespace (blanks and tabs) and |
| then parse the first nonwhitespace character. This character can be |
| only a carriage return or a forward slash (/). If a carriage return |
| then parsing is finished. We would then display the current hotkey |
| status and exit if this is a second install attempt or continue with |
| the install logic. If this is a slash then we check for either a B, |
| K, or U character immediately following. The B character indicates |
| that we want to set the BEEP state. The K character indicates that |
| we want to set the HOTKEY. The U character indicates that we want |
| to UNINSTALL. If B is selected then we parse the next character |
| following the B (must be 0 for disable or 1 for enable) and save it. |
| If K is selected then we parse the next character following the K |
| (must be A-Z or 0-9 - a-z is converted to A-Z) and save it. In the |
| event of B or K as the command option, we continue parsing. If U is |
| selected then we check to see if a copy of this TSR already exists. |
| If it does then we attempt to uninstall. Otherwise, we display an |
| error message and exit. |
| |
| A call to an xparse () function defined in the application will fol- |
| low if this extension option is specified. This gives the applica- |
| tion the ability to extend command tail parsing. Numerous examples |
| of this can be found in TSREX.ZIP. This function returns nonzero if |
| an error is detected during the extended parse. Otherwise, command |
| tail parsing resumes. The B, K, and U options will always override |
| any equivalent options defined in xparse (). Therefore, they will |
| never be passed to xparse () and there is no point in trying to use |
| them. |
| |
| The next step is application-specific. Some applications may need |
| to perform additional setup such as redirecting other interrupt vec- |
| tors. If this is the case then the installation kernel would call a |
| setup () function defined in the application. The setup () function |
| returns nonzero if an error is detected. |
| |
| The next part of the install logic is to redirect the HIMEM.SYS XMS |
| handler if the current version of DOS is 5.0 or higher and HIMEM.SYS |
| has been installed. |
| |
| Interrupts 8, 9, 13h, 28h, and 2fh are redirected. Note that inter- |
| rupt 9 is redirected last to ensure that all other interrupts are |
| installed in case the hotkey is pressed before we finish the instal- |
| lation. At the same time, the environment segment is freed. Note |
| that we obtain the current addresses of interrupt 16h and 1ch. The |
| launch sequence procedure requires this information. |
| |
| Finally, we calculate the amount of memory (in paragraphs) to keep |
| and terminate but stay resident. |
------------------------------------------------------------------------
- 8 -
------------------------------------------------------------------------
| |
| It would be instructive to take a look at the uninstall procedure. |
| The first step is to ensure that interrupts 8, 9, 13h, 28h, and 2fh |
| match their saved addresses. We cannot uninstall if any different |
| address is detected. This would indicate that the TSR is not the |
| most recently installed. If all interrupts match then we restore |
| them to their saved addresses. We then attempt to call cleanup () |
| in the application (if defined for the application). Any addtional |
| redirected interrupts would be restored as well as any other cleanup |
| tasks. A nonzero value is returned if cleanup is unsuccessful. In |
| previous versions of TSR TOOLKIT, no value was returned. This fea- |
| ture has been added to version 1.5 to ensure a more reliable kernel. |
| We attempt to release all memory previously allocated when we TSRed. |
| If cleanup is unsuccessful or we cannot release this memory then we |
| display a reboot error message and exit. Otherwise we display a |
| success message and exit. |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
------------------------------------------------------------------------
- 9 -
------------------------------------------------------------------------
| |
| Sound API |
| --------- |
| |
| * void beep (void); |
| |
| Generate a beep for 1/3 of a second. |
| |
| * void nosound (void); |
| |
| Disable sound. |
| |
| * void pause (unsigned ticks); |
| |
| Generate a delay in timer ticks. By default, the tick rate is 18.2 |
| ticks per second (approximately). The minimum value passed to this |
| function should be 1 tick otherwise you might be waiting for a very |
| long time. There is the possibility, due to the unpredictability of |
| when a timer interrupt occurs that you may lose one tick. I have |
| not come up with any solution to this problem. |
| |
| * void sound (unsigned frequency); |
| |
| Enable sound at the specified frequency. The lowest valid frequency |
| is 19 Hertz. Any lower value and sound () immediately exits. |
| |
| |
| These functions are prototyped in TSRLIB.H (see TSRLIB.ZIP). |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
------------------------------------------------------------------------
- 10 -
------------------------------------------------------------------------
| |
| XMS API |
| ------- |
| |
| One of the best things added to DOS 5.0, as far as I am concerned, |
| was HIMEM.SYS. At last, a decent gateway to extended memory. TSR |
| TOOLKIT takes advantage of this capability. |
| |
| typedef struct |
| { |
| long length; |
| unsigned srchandle; |
| long srcoffset; |
| unsigned desthandle; |
| long destoffset; |
| } |
| EMMS; /* Extended Memory Move Structure */ |
| |
| * int XMS_Alloc (unsigned nkilos); |
| |
| Attempt to allocate a block of extended memory in kilobytes. If no |
| error occurs then a handle is returned. This handle references the |
| extended memory region indirectly. If an error occurs then zero is |
| returned. |
| |
| * int XMS_Copy (EMMS *x); |
| |
| This function allows you to copy a block of conventional memory to |
| extended memory or the other way around. You need to create an EMMS |
| variable and fill it in appropriately. The length specifies the |
| number of bytes to copy and must be an even number. The handles |
| cannot come from locked extended memory blocks. If zero is the han- |
| dle then the offset field would specify the segment:offset address |
| in conventional memory where the block starts. Zero is returned on |
| failure. See XMS.C in TSREX.ZIP for an example. |
| |
| * int XMS_Exists (void); |
| |
| This function returns a nonzero value if HIMEM.SYS is not installed. |
| |
| * int XMS_Free (unsigned handle); |
| |
| This function frees a previously allocated block. It returns zero |
| on failure. |
| |
| |
| |
| |
| |
| |
------------------------------------------------------------------------
- 11 -
------------------------------------------------------------------------
| |
| * long XMS_Lock (unsigned handle); |
| |
| This function attempts to lock a memory block to a specific address. |
| If successful then the 32-bit linear address of this block will be |
| returned. Zero is returned otherwise. This allows you to work with |
| this block directly via the BIOS int 15h facility. |
| |
| * int XMS_Query (unsigned *nkilos, unsigned *maxblocksize); |
| |
| This function returns the total number of kilobytes of available |
| extended memory in *nkilos and the size of the largest block in |
| *maxblocksize. Both values take the high memory area (HMA) which is |
| 64K in length into account. Zero is returned on error. |
| |
| * int XMS_Realloc (unsigned handle, unsigned nkilos); |
| |
| This function allows you to adust the size of a memory block. Zero |
| is returned on error. |
| |
| * int XMS_Unlock (unsigned handle); |
| |
| This function performs the inverse of XMS_Lock (). Zero is returned |
| on error. |
| |
| |
| These functions are prototyped in TSRLIB.H (see TSRLIB.ZIP). |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
------------------------------------------------------------------------
- 12 -
------------------------------------------------------------------------
| |
| Install API |
| ----------- |
| |
| * int cleanup (void); |
| |
| This is the prototype for the cleanup () function which must be |
| defined in the application source file if you decide to incorporate |
| setup/cleanup. A nonzero value must be returned on error or zero on |
| success. |
| |
| * int parse (void); |
| |
| This function returns the next character on the command tail. The |
| parse position is updated unless a carriage return is returned. |
| |
| * void setcseg (void); |
| |
| This function sets both the DS and ES registers to the current seg- |
| ment (the same segment as CS) and is used with xparse (). |
| |
| * void setrseg (void); |
| |
| This function sets both the DS and ES registers to the resident seg- |
| ment and is used with xparse (). |
| |
| * int setup (void); |
| |
| This is the prototype for the setup () function which must be |
| defined in the application source file if you decide to incorporate |
| setup/cleanup. A nonzero value must be returned on error or zero on |
| success. |
| |
| * void skipws (void); |
| |
| This function skips leading whitespace on the command tail. White- |
| space consists of blanks and tabs. |
| |
| * void unparse (void); |
| |
| This function backs up the parse pointer by one position unless the |
| pointer is pointing to a carriage return. |
| |
| * int xparse (int option); |
| |
| This is the prototype for the xparse () function which must be |
| defined in the application source file if you decide to incorporate |
| extended parsing. The option passed is the character which follows |
| the / on the command tail. A nonzero value must be returned on |
| error or zero on success. |
------------------------------------------------------------------------
- 13 -
------------------------------------------------------------------------
| |
| Tools |
| ----- |
| |
| TSR TOOLKIT provides two utility programs and a batch file that work |
| together with BCC.EXE, TASM.EXE, and TLINK.EXE to generate TSRs from |
| C source files. |
| |
| T.BAT serves as the crux. It calls all other programs in a proper |
| sequence. The format of the T command line is: |
| |
| T filename arguments |
| |
| The filename consists of the TSR .C name with an optional drive and |
| path. A file extension must not be specified since T.BAT appends a |
| .C to the filename. |
| |
| The arguments which will shortly be discussed consist of either a - |
| or / character followed by a sequence of characters. Each argument |
| must be separated by whitespace (blanks and/or tabs). These argu- |
| ments may appear in any order but must follow the file name. |
| |
| * -hx |
| |
| h is the hotkey argument. Any letter A-Z or digit 0-9 may appear in |
| place of the x. This letter/digit when combined with ALT serves as |
| the default hotkey. |
| |
| * -i |
| |
| i is the include argument. This argument causes the contents of |
| EXTRA.ASM to be included after the application code. |
| |
| * -sy |
| |
| s is the stack argument. This argument specifies the size of the |
| TSR stack (y ranges from the default of 256 to 8192 bytes). |
| |
| * -sc |
| |
| sc is the setup/cleanup argument. This argument allows the instal- |
| lation kernel to incorporate calls to setup () and cleanup (). They |
| must be defined in the application source file. |
| |
| * -x |
| |
| x is the xparse argument. This argument allows the installation |
| kernel to incorporate a call to xparse (). This must be defined in |
| the application source file. |
| |
------------------------------------------------------------------------
- 14 -
------------------------------------------------------------------------
| |
| What does T.BAT do? After parsing the command line, it calls the |
| BCC.EXE program to compile the application .C file and create an |
| equivalent assembler source file (via the -S switch). At this time, |
| the TI environment variable is passed to BCC.EXE telling it where to |
| find the TSRLIB source files should any be referenced in the app. |
| If everything is successful then FILTER.EXE is called. BCC.EXE will |
| generate a file with an .ASM extension which is the equivalent of |
| the .C file. However, this file is not in a format suitable for |
| turning into a TSR. FILTER.EXE takes this .ASM file and turns it |
| into a properly formatted file with a .TSR extension. This is then |
| passed to TSR.EXE which creates a sandwich .ASM file. The .TSR file |
| is placed between the resident and installation kernels. Once this |
| has been accomplished, the resulting .ASM file is assembled and then |
| linked. TLINK.EXE creates a .COM file directly. If any errors are |
| detected during any step then T.BAT displays an error message and |
| aborts. |
| |
| Note that TSR.EXE takes identical arguments as T.BAT but in reverse |
| order. Don't let that be a point of confusion. Always use T.BAT. |
| Each example program (see TSREX.ZIP) shows the calling sequence via |
| T.BAT in the comments section at the start of the source file. |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
------------------------------------------------------------------------
- 15 -